package com.hjk.common.utils.bean;

import com.alibaba.fastjson.JSON;
import com.hjk.common.utils.check.Check;
import lombok.SneakyThrows;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author huangjunkai
 * @date 2019/7/8
 */
public class MyBeanUtils {
    private static Logger log = LoggerFactory.getLogger(MyBeanUtils.class);

    /**
     * 方法说明：将bean转化为另一种bean实体
     *  
     *
     * @param object
     * @param entityClass
     * @return
     */
    public static <T> T convertBean(Object object, Class<T> entityClass) {
        if (null == object) {
            return null;
        }
        return JSON.parseObject(JSON.toJSONString(object), entityClass);
    }


    /**
     * 方法说明：对象转换
     *  
     *
     * @param source           原对象
     * @param target           目标对象
     * @param ignoreProperties 排除要copy的属性
     * @return
     */
    @SneakyThrows
    public static <T> T copy(Object source, Class<T> target, String... ignoreProperties) {
        T targetInstance = target.newInstance();
        if (ObjectUtils.isEmpty(ignoreProperties)) {
            BeanUtils.copyProperties(source, targetInstance);
        } else {
            BeanUtils.copyProperties(source, targetInstance, ignoreProperties);
        }
        return targetInstance;

    }

    /**
     * 方法说明：对象转换(List)
     *  
     *
     * @param list             原对象
     * @param target           目标对象
     * @param ignoreProperties 排除要copy的属性
     * @return
     */
    public static <T, E> List<T> copyList(List<E> list, Class<T> target, String... ignoreProperties) {
        List<T> targetList = new ArrayList<>();
        if (ObjectUtils.isEmpty(list)) {
            return targetList;
        }
        list.forEach(e -> targetList.add(copy(e, target, ignoreProperties)));
        return targetList;
    }

    /**
     * 方法说明：map转化为对象
     */
    public static <T> T mapToObject(Map<String, Object> map, Class<T> t) {
        try {
            T instance = t.newInstance();
            org.apache.commons.beanutils.BeanUtils.populate(instance, map);
            return instance;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 方法说明：对象转化为Map
     *  
     *
     * @param object
     * @return
     */
    public static Map<?, ?> objectToMap(Object object) {
        return convertBean(object, Map.class);
    }


    /**
     * 对象拷贝
     *
     * @param source 原对象
     * @param target 目标对象
     * @param <T>
     * @return
     */
    public static <T> T copyProperties(Object source, Class<T> target) {
        try {
            T t = target.newInstance();
            BeanUtils.copyProperties(source, t);
            return t;
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
        }
        return null;

    }


    /**
     * List集合拷贝
     *
     * @param sourceList 原集合
     * @param target     目标集合
     * @param <T>        目标集合泛型
     * @return
     */
    public static <T> List<T> copyWithCollection(List<?> sourceList, Class<T> target) {
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
        }
        return new ArrayList<>();
    }

    /**
     * set集合拷贝
     *
     * @param sourceList 原集合
     * @param target     目标集合
     * @param <T>        目标集合泛型
     * @return
     */
    public static <T> Set<T> copyWithCollection(Set<?> sourceList, Class<T> target) {
        try {
            return sourceList.stream().map(s -> copyProperties(s, target)).collect(Collectors.toSet());
        } catch (Exception e) {
            log.error("【数据转换】数据转换出错，目标对象{}构造函数异常", target.getName(), e);
        }
        return new HashSet<>();
    }


    /**
     * 将object转换为list
     */
    public static <Q,R> List<R> castList(List<Q> list, Class<R> clazz) {
        if (Check.isNotEmpty(list)) {
            return list.stream().map(clazz::cast).collect(Collectors.toList());
        }
        return null;
    }
}
